package jwt

import (
	"bluebell/settings"
	"errors"
	"github.com/golang-jwt/jwt/v4"
	"time"
)

//TokenExpireDuration Token过期时间
var TokenExpireDuration = 24 * time.Hour

//CustomSecret  签名加盐
var CustomSecret = []byte("hedadaolikefish")

//CustomClaims 自定义token的payload部分
type CustomClaims struct {
	UserID               uint `json:"userid"` //自定义字段
	jwt.RegisteredClaims      // 内嵌标准的声明
}

// GenToken 生成token
func GenToken(userid uint) (string, error) {
	// 创建一个我们自己的声明
	claims := CustomClaims{
		userid,
		jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(TokenExpireDuration)),
			Issuer:    settings.Config.Auth.Issuer, // 签发人
		},
	}
	// 使用指定的签名方法创建签名对象
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) //SigningMethodHS256是加密算法
	// 使用指定的secret进行签名，并返回完整的编码后的字符串token
	return token.SignedString(CustomSecret)
}

// ParseToken 解析token
func ParseToken(tokenString string) (*CustomClaims, error) {
	mc := new(CustomClaims)
	// 直接使用标准的Claim则可以直接使用Parse方法
	//token, err := jwt.Parse(tokenString, func(token *jwt.Token) (i interface{}, err error) {}
	// 如果是自定义Claim结构体则需要使用 ParseWithClaims 方法
	token, err := jwt.ParseWithClaims(tokenString, mc, func(token *jwt.Token) (i interface{}, err error) {
		return CustomSecret, nil
	})
	if err != nil {
		return nil, err
	}
	// 对token对象中的Claim进行类型断言
	if token.Valid { // 校验token
		return mc, nil
	}
	return nil, errors.New("无效的token")
}
